#include "ricvc.h"

void grey(int width, int height, unsigned char *src, unsigned char *dest) {
    int i, j;
    unsigned char r, g, b, c, newc;

    for (j=0; j<height; j++)
        for (i=0; i<width; i++) {
            c=src[(j*width)+i];
            r=pal[(c+(c<<1))];
            g=pal[(c+(c<<1))+1];
            b=pal[(c+(c<<1))+2];
            newc=(r+g+b)/6;
            if (!newc && c)
                newc=1;
            dest[(j*width)+i]=newc;
        }
}

void VCvline(int x, int y, int y2, unsigned char c)
{
    int i, j;
    i=y2-y;

    do {
        i--;
        j=y+i;
        vcscreen[(j<<8) + (j<<6)+x]=c;
    } while (i);
    /*  for (i=0; i<(y2-y); i++) {
     j=y+i;
     vcscreen[(j<<8) + (j<<6)+x]=c;
     } */
}

void VCColorField(int x1, int y1, int x2, int y2, unsigned char *colortbl)
/* -- ric: 22/Apr/98 -- */
/* Simulate the ColorField function on the VC layer.
 * Used wrong spelling so as to avoid confusing the Americans ;)
 * Note: the visible screen starts at (16,16) on the virscr buffer while
 *       vcscreen starts at (0,0). We need to redraw the screen before
 *       drawing the ColorField to achieve the translucency effect.
 */
{
    int j, i, k;
    unsigned char c;
    unsigned char *tmpscreen;

    tmpscreen=virscr+5632; /* Make tmpscreen point to the virscr buffer, */
    /* offsetting by 5632 (16*352, i.e. 16 lines) */
    drawmap(); /* Redraw the map                             */

    j=y1;
    do {
        i=x1;
        do {
            k=(j<<8)+(j<<6); /* k=j*320                       */
            c=tmpscreen[k+(j<<5)+i+16]; /* k+(j<<5)=j*352                */
            vcscreen[k+i]=colortbl[c];
            i++;
        } while (i!=x2);
        j++;
    } while (j!=y2);

    //  for (j=y1; j<y2; j++)
    //    for (i=x1; i<x2; i++)
    //      { k=(j<<8)+(j<<6);              /* k=j*320                       */
    //        c=tmpscreen[k+(j<<5)+i+16];   /* k+(j<<5)=j*352                */
    //       vcscreen[k+i]=colortbl[c];
    //      }
}

void VCborder(int x1, int y1, int x2, int y2)
/* -- ric: 21/Apr/98 -- */
/* Taken from MENU2.C and adapted for the VC layer
 */
{
    VCvline(x1+1, y1+1, y2-1, grey1);
    VCvline(x1+2, y1+2, y2-2, grey2);
    VCvline(x1+3, y1+2, y2-2, grey2);
    VCvline(x1+4, y1+3, y2-3, grey1);

    VCvline(x2-1, y1+1, y2-1, grey1);
    VCvline(x2-2, y1+2, y2-2, grey2);
    VCvline(x2-3, y1+2, y2-2, grey2);
    VCvline(x2-4, y1+3, y2-3, grey1);

    VChline(x1+1, y1+1, x2-1, grey1);
    VChline(x1+2, y1+2, x2-2, grey2);
    VChline(x1+4, y1+3, x2-4, grey1);

    VChline(x1+1, y2-1, x2, grey1);
    VChline(x1+2, y2-2, x2-1, grey2);
    VChline(x1+4, y2-3, x2-3, grey1);
}

void VCBox()
{
    int x1, y1, x2, y2;
    x1=ResolveOperand();
    y1=ResolveOperand();
    x2=ResolveOperand();
    y2=ResolveOperand();

    //  for (i=y1; i<=y2; i++)
    //      VChline(x1,i,x2+1,bgcolor);
    VCColorField(x1, y1, x2+1, y2+1, menuxlatbl);
    VCborder(x1, y1, x2, y2);
}

void VCAString(int x1, int y1, char* strng, int align)
{
    if (align==1)
        x1-=(strlen(strng)<<2);
    if (align==2)
        x1-=(strlen(strng)<<3);
    VCprintstring(x1, y1, strng);
}

void VCCharName()
{
    int x1, y1, i, align;

    x1=ResolveOperand();
    y1=ResolveOperand();
    i=ResolveOperand();
    align=ResolveOperand();
    VCAString(x1, y1, party_stats[i].name, align);
}

void VCItemName()
{
    int x1, y1, i, align;

    x1=ResolveOperand();
    y1=ResolveOperand();
    i=ResolveOperand();
    align=ResolveOperand();
    VCAString(x1, y1, items[i].name, align);
}

void VCItemDesc()
{
    int x1, y1, i, align;

    x1=ResolveOperand();
    y1=ResolveOperand();
    i=ResolveOperand();
    align=ResolveOperand();
    VCAString(x1, y1, items[i].desc, align);
}

void VCItemImage()
{
    int x1, y1, i, gf;
    unsigned char gsimg[512];
    unsigned char *img;

    x1=ResolveOperand();
    y1=ResolveOperand();
    i=ResolveOperand();
    gf=ResolveOperand();
    img=itemicons+(items[i].icon<<8);
    if (gf) {
        grey(16, 16, img, gsimg);
        img=gsimg;
    }

    VCtcopysprite(x1, y1, 16, 16, img);
}

void VCATextNum()
{
    int x1, y1, i, align;
    char stringbuf[100];

    x1=ResolveOperand();
    y1=ResolveOperand();
    i=ResolveOperand();
    align=ResolveOperand();
    dec_to_asciiz(i, stringbuf);
    VCAString(x1, y1, stringbuf, align);
}

void VCSpc()
{
    int x1, y1, i, gf;
    unsigned char gsimg[1024];
    unsigned char *img;

    x1=ResolveOperand();
    y1=ResolveOperand();
    i=ResolveOperand();
    gf=ResolveOperand();
    img=speech+(1024*i);
    if (gf) {
        grey(32, 32, img, gsimg);
        img=gsimg;
    }

    VCtcopysprite(x1, y1, 32, 32, img);
}

void CallEffect()
{
    char varcnt;
    unsigned char* buf;
    unsigned char* basebuf;
    int i;
    unsigned short int t;
    int savetvar[26];

    varcnt=GrabC();
    t=ResolveOperand();

    for (i=0; i<varcnt; i++)
        varl[i]=ResolveOperand();

    buf=code;
    basebuf=basevc;
    memcpy(savetvar, tvar, sizeof(tvar));
    ExecuteEffect(t);
    memcpy(tvar,savetvar,sizeof(tvar));
    code=buf;
    basevc=basebuf;
}

void ExecuteStartUpScript(unsigned short s) {
    basevc = startupvc;
    code = startupvc + startupofstbl[s];

    ExecuteBlock();
}

void CallScript()
{
    char varcnt;
    unsigned char* buf;
    unsigned char* basebuf;
    int i;
    unsigned short int t;
    int savetvar[26];

    varcnt=GrabC();
    t=ResolveOperand();

    for (i=0; i<varcnt; i++)
        varl[i]=ResolveOperand();

    buf=code;
    basebuf=basevc;
    memcpy(&savetvar, &tvar, sizeof(tvar));

    ExecuteStartUpScript(t);

    memcpy(&tvar,&savetvar,sizeof(tvar));
    code=buf;
    basevc=basebuf;
}

void BindKey()
{
    int ky, scrpt;
    ky=ResolveOperand();
    scrpt=ResolveOperand();
    key_map[ky].boundscript=scrpt;
}

void TextMenu() {
    unsigned char* buf1;
    unsigned char* buf2;
    unsigned char* opt;
    int first=1, nv, p, ptr=0, ansave;
    int x1, y1, flagidx, width=0;

    ansave=an;
    an=1;

    x1=ResolveOperand();
    y1=ResolveOperand();
    flagidx=ResolveOperand();
    ptr=ResolveOperand();
    if (ptr)
        ptr--;

    nv=GrabC();
    buf1=code;
    for (p=0; p<nv; p++) {
        opt=code;
        GrabString(strbuf);
        if (width<(int)strlen((char*)opt))
            width=strlen((char*)opt);
    }
    buf2=code;

    drawloop: drawmap();
    tmenubox(x1+16, y1+16, x1+66+(width*8), y1+28+(nv*10));
    for (p=0; p<nv; p++) {
        opt=code;
        GrabString(strbuf);
        gotoxy(x1+41, 23+y1+(p*10));
        printstring((char*)opt);
    }
    buf2=code;
    code=buf1;
    tcopysprite(23+x1, 21+y1+(ptr*10), 16, 16, menuptr);
    vgadump();
    readcontrols();
    if (first==2) {
        if (b1 || b2 || b4)
            goto drawloop;
        else {
            an=ansave;
            code=buf2;
            flags[flagidx]=0;
            return;
        }
    }
    if (first && !b1 && !b2 && !b4 && !down && !up)
        first=0;
    else if (first)
        goto drawloop;

    if (down) {
        ptr++;
        if (ptr==nv)
            ptr=0;
        playeffect(0);
        first=1;
    }
    if (up) {
        if (!ptr)
            ptr=nv-1;
        else
            ptr--;
        playeffect(0);
        first=1;
    }

    if (b1) {
        an=ansave;
        code=buf2;
        flags[flagidx]=ptr+1;
        return;
    }

    while (!b4 && !b2)
        goto drawloop;
    while (b4 || b2) {
        first=2;
        goto drawloop;
    }

    an=ansave;
    code=buf2;
    flags[flagidx]=0;
    return;
}

void itemMenu()
{
    int c;
    c=ResolveOperand();
    ItemMenu(c-1);
}

void equipMenu()
{
    int c;
    c=ResolveOperand();
    EquipMenu(c-1);
}

void magicMenu()
{
    int c;
    c=ResolveOperand();
    MagicMenu(c-1);
}

void statusScreen()
{
    int c;
    c=ResolveOperand();
    StatusScreen(c);
}

void VCCr2()
{
    int x1, y1, i, gf;
    unsigned char gsimg[9216];
    unsigned char *img;

    x1=ResolveOperand();
    y1=ResolveOperand();
    i=ResolveOperand();
    gf=ResolveOperand();
    img=chr2+(9216*(i-1));
    if (gf) {
        grey(96, 96, img, gsimg);
        img=gsimg;
    }

    VCtcopysprite(x1, y1, 96, 96, img);
}

void VCTextBox() {
    unsigned char* buf1;
    unsigned char* buf2;
    unsigned char* opt;
    int nv, p, ptr=0;
    int x1, y1, width=0;

    x1=ResolveOperand();
    y1=ResolveOperand();
    ptr=ResolveOperand();

    nv=GrabC();
    buf1=code;
    for (p=0; p<nv; p++) {
        opt=code;
        GrabString(strbuf);
        if ((unsigned int)width<strlen((char*)opt))
            width=strlen((char*)opt);
    }
    buf2=code;
    code=buf1;

    VCColorField(x1, y1, x1+51+(width*8), y1+13+(nv*10), menuxlatbl);
    VCborder(x1, y1, x1+50+(width*8), y1+12+(nv*10));

    for (p=0; p<nv; p++) {
        opt=code;
        GrabString(strbuf);
        VCprintstring(x1+25, y1+7+(p*10), (char*)opt);
    }
    if (ptr)
        VCtcopysprite(7+x1, 5+y1+((ptr-1)*10), 16, 16, menuptr);
}

void VCMagicImage() {
    int x1, y1, i, gf;
    unsigned char gsimg[512];
    unsigned char *img;

    x1=ResolveOperand();
    y1=ResolveOperand();
    i=ResolveOperand();
    gf=ResolveOperand();
    img=magicicons+(magic[i].icon<<8);
    if (gf) {
        grey(16, 16, img, gsimg);
        img=gsimg;
    }

    VCtcopysprite(x1, y1, 16, 16, img);
}

int ChooseChar(int x1, int y1)
/* Returns roster order of selected character or zero if cancelled */
{
    int first=1, ptr=0, j, ansave;
    unsigned char l;

    ansave=an;
    an=1;

    drawloop: drawmap();
    tmenubox(x1+16, y1+16, x1+111, y1+28+(numchars*10));

    for (j=0; j<numchars; j++) {
        l=partyidx[j]-1;
        gotoxy(x1+41, y1+22+(j*10));
        printstring(party_stats[l].name);
    }

    tcopysprite(x1+23, y1+20+(ptr*10), 16, 16, menuptr);
    vgadump();

    readcontrols();
    if (first==2) {
        if (b1 || b2 || b4)
            goto drawloop;
        else {
            an=ansave;
            return 0;
        }
    }
    if (first && !b1 && !b2 && !b4 && !down && !up)
        first=0;
    else if (first)
        goto drawloop;

    if (down) {
        ptr++;
        if (ptr==numchars)
            ptr=0;
        playeffect(0);
        first=1;
    }
    if (up) {
        if (!ptr)
            ptr=numchars-1;
        else
            ptr--;
        playeffect(0);
        first=1;
    }

    if (b1) {
        an=ansave;
        return ptr+1;
    }

    while (!b4 && !b2)
        goto drawloop;
    while (b4 || b2) {
        first=2;
        goto drawloop;
    }

    an=ansave;
    return 0;
}

